﻿package  Classes{
	
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.events.*;
	import flash.geom.Point;
	import flash.utils.Timer;
	import flash.utils.Dictionary;
	import flash.display.Bitmap;
	import Asserts.Thinking;
	
	public class Board extends MovieClip {
		//Array Size of the board
		public static const BOARD_WIDTH:int = 5;
		public static const BOARD_HEIGHT:int = 12;
		public static const INVALID_BOARD_TAG:uint = 0x00;
		//STATIONS - 大本营，行营，兵站 （分公路上的和铁路上的）
		public static const HEADQUARTER:uint = 0x71;
		public static const CAMP:uint = 0x72;
		public static const STATION_ROAD:uint = 0x73;
		public static const STATION_RAILWAY:uint = 0x74;
		//the default line-up file length: 50 bytes 
		public static const LINEUP_FILE_BYTE_LENGTH:int = 50;
		//move and attack result
		public static const INVALID_MOTION:int = 1000;
		public static const MOVE:int = 1001;
		public static const KILL:int = 1002;
		public static const EQUAL:int = 1003;
		public static const KILLED:int = 1004;
		public static const MAN_LOST:int = 1005;
		public static const AI_LOST:int = 1006;
		
		// all the stations
		private var stations:Array = new Array();
		// Array of the board
		private var boardArea:Array = new Array();
		// it's for A* path finding 
		private var openList:Array;
		private var closedList:Array;
		// For update physics (update board)
		private var mPath:Array;
		private var from:Coordinate;
		private var to:Coordinate; 	// on touch event
		private var from0:Coordinate;
		private var to0:Coordinate; // last from and to, to draw the red tag
		private var curStep:int = 0;
		private var moveAndAttackResult:int ;
		private var mSourcePiece:int; 
		private var allChess:Dictionary;
		
		private var lastSelected:int = -1;
		
		private var defaultBoard:Array ;
		//default board
		public static const GS_BUJU:int = 1;
		public static const GS_PLAYING:int =2;
		public static const GS_OVER:int = 3;
		public var GameState:int = GS_PLAYING;
		private var robot:ABSearch;
		private var robotTimer:Timer;
		private var flipTimer:Timer;
		private var allPathPoint:Array = new Array;
		private var steps:int = 0;
		private static const MAX_STEP = 250;
		private var mcSelected:SelBox;
		private var imgThink:Bitmap;
		public var instance:Main;
		public function Board() {
			robot = new ABSearch(this);
			initBoard();
			addEventListener(Event.ADDED_TO_STAGE,addToStage);
			imgThink = new Bitmap();
			imgThink.bitmapData = new Asserts.Thinking();
			imgThink.x = 140;
			imgThink.y = 235;
			imgThink.visible = false;
			addChild(imgThink);
		}
		
		public function clickBoard(row:int,col:int):void 
		{
			var curSelected:int = row*5+col;
			var oRow:int = -1;
			var oCol:int = -1;
			if(lastSelected == -1) {
				if(boardArea[row][col] == Board.INVALID_BOARD_TAG || Pieces.getLocated(boardArea[row][col]) !=Pieces.MAN_TAG) 
				{
					return;
				}
				else {
					lastSelected = row*5+col;
					mcSelected.visible = true;
					var orgPos:Point = Main.instance.rowcolToPostion(row,col);
					mcSelected.x = orgPos.x;
					mcSelected.y = orgPos.y;
					(new sndSelect).play();
				}
				return;
			}
			if(curSelected == lastSelected ) {
				lastSelected = -1;
				mcSelected.visible = false;
				return;
			}
			
			//target is empty.only move
			oRow = lastSelected/5;
			oCol = lastSelected%5;
			
			if(this.GameState == GS_PLAYING)
			{
				if(Pieces.getLocated(boardArea[row][col]) ==Pieces.MAN_TAG) {
					lastSelected = -1;
					mcSelected.visible = false;
					return;
				}
				mPath = pathFinding(oCol,oRow , col,row);
				if (mPath == null || mPath.length<1) {
					return;
				}
				showPath(oRow,oCol,mPath);
				moveAndAttackResult = moveAndAttack(oCol,oRow , col,row);
				var chess:Chess = this.getChessAt(oRow,oCol);
				var targetChess:Chess = this.getChessAt(row,col);
				var srcChess:int =  boardArea[oRow][oCol];
				var dstChess:int = boardArea[row][col];
				lastSelected = -1;
				var msg:String = "";
				robot.MakeMoveRC(oRow,oCol,row,col);
				switch (moveAndAttackResult) {
					case MOVE:
					case KILL:
					case AI_LOST:
					case MAN_LOST:
						robot.DelPiece(oRow,oCol);
						robot.DelPiece(row,col);
						robot.AddPiece(row,col,srcChess);
						var p:Point = Main.instance.rowcolToPostion(row,col);
						chess.x = p.x;
						chess.y = p.y;						
						if(targetChess != null) {
							this.removeChild(targetChess);
							msg = msg+"你的"+chess.title+"消灭了对方的"+targetChess.title+".";
						}
						setChess(row,col,chess);
						setChess(oRow,oCol,null);
						
					break;
					case EQUAL:
						robot.DelPiece(oRow,oCol);
						robot.DelPiece(row,col);
						msg = msg+"你的"+chess.title+"和对方的"+targetChess.title+"同归于尽了.";

						this.removeChild(targetChess);
						this.removeChild(chess);
						setChess(row,col,null);
						setChess(oRow,oCol,null);
					break;
					case KILLED:
						robot.DelPiece(oRow,oCol);
						msg = msg+"你的"+chess.title+"被对方的"+targetChess.title+"干掉了.";

						this.removeChild(chess);
						setChess(oRow,oCol,null);
					break;
				}
				robot.printZobr();
				steps++;
				(new sndMove).play();
				Main.instance.showMessage(msg);
				this.checkGame();
				if(GameState == Board.GS_PLAYING) {
					imgThink.visible = true;
					var robotTimer:Timer = new Timer(400,1);
					robotTimer.addEventListener(TimerEvent.TIMER_COMPLETE,this.onTimer);
					robotTimer.start();
				}
			}
			
			/*if(boardArea[row][col] == Board.INVALID_BOARD_TAG)
			{
				boardArea[row][col] = boardArea[oRow][oCol];
				boardArea[oRow][oCol] = Board.INVALID_BOARD_TAG;
				
				var chess:Chess = this.getChessAt(oRow,oCol);
				var p:Point = Main.instance.rowcolToPostion(row,col);
				chess.x = p.x;
				chess.y = p.y;
				setChess(row,col,chess);
				setChess(oRow,oCol,null);
				lastSelected = -1;
			}*/
			
		}
		
		private function setChess(row:int,col:int,chess:Chess)
		{
			var key = row+"_"+col;
			allChess[key] = chess;
		}
		
		private function initDefaultBoard():void
		{
			defaultBoard = new Array;
			defaultBoard[0] = [0x13,0x12,0x13,0x1C,0x18];
			defaultBoard[1] = [0x1B,0x13,0x14,0x19,0x1B];
			defaultBoard[2] = [0x1C,0x00,0x1D,0x00,0x1A];
			defaultBoard[3] = [0x17,0x19,0x00,0x18,0x1C];
			defaultBoard[4] = [0x17,0x00,0x15,0x00,0x14];
			defaultBoard[5] = [0x1D,0x16,0x1B,0x1D,0x1A];

			defaultBoard[6] = [0x0D,0x06,0x0B,0x0D,0x0A];
			defaultBoard[7] = [0x07,0x00,0x05,0x00,0x04];
			defaultBoard[8] = [0x07,0x09,0x00,0x08,0x0C];
			defaultBoard[9] = [0x0C,0x00,0x0D,0x00,0x0A];
			defaultBoard[10] = [0x0B,0x03,0x04,0x09,0x0B];
			defaultBoard[11] = [0x03,0x02,0x03,0x0C,0x08];
			
			var tempBoard:Array = getRandomBoard();
			for(var i:int=0;i<6;i++) {
				for(var j:int =0;j<5;j++) {
					defaultBoard[i][j] = tempBoard[i][j];
				}
			}
			
			var tempBoard2:Array = getRandomBoard();
			for(i=0;i<6;i++) {
				for(j =0;j<5;j++) {
					defaultBoard[11-i][4-j] = (tempBoard2[i][j]&0x0F);
				}
			}
			
			//random it.bomb can not be placed at first row.mine can be palced last two row only.
			//first place flag,then palce bomb,last other chesses.
		}
		//返回一个随机的布局
		private function getRandomBoard():Array
		{
			var standBoard:Array = new Array();
			standBoard[0] = [0x13,0x12,0x13,0x1C,0x18];
			standBoard[1] = [0x1B,0x13,0x14,0x19,0x1B];
			standBoard[2] = [0x1C,0x00,0x1D,0x00,0x1A];
			standBoard[3] = [0x17,0x19,0x00,0x18,0x1C];
			standBoard[4] = [0x17,0x00,0x15,0x00,0x14];
			standBoard[5] = [0x1D,0x16,0x1B,0x1D,0x1A];
			//先放军旗 随机选个位置
			if(Math.random()*100<50) {
				swapChess(standBoard,0,1,0,3);
				swapChess(standBoard,0,0,0,4);
				swapChess(standBoard,1,1,1,3);
			}
			//随机摆放其它棋子
			var i:int =1000;
			while(i>0) {
				var p1:int = Math.random()*29;
				var p2:int = Math.random()*29;
				var c1:int = p1%5;
				var r1:int = p1/5;
				var c2:int = p2%5;
				var r2:int = p2/5;
				//忽略军旗和地雷
				if(standBoard[r1][c1] == 0x12 || standBoard[r1][c1] == 0x13 || standBoard[r1][c1]==0x00) continue;
				if(standBoard[r2][c2] == 0x12 || standBoard[r2][c2] == 0x13 || standBoard[r2][c2] == 0x00) continue;
				swapChess(standBoard,r1,c1,r2,c2);
				i--;
			}
			//if bomb is at first row swap with 1~4
			while(1) {
				var finded:Boolean = false;
				for(i =0;i<5;i++) {
					if(standBoard[5][i]==0x14){
						finded = true;
						break;
					}
				}
				if(!finded) break;
				if(finded) {
					//find a place that not 0x00,0x14
					var r3:int = -1;
					var c3:int = 1;
					while(1) {
						var p3:int = Math.random()*19+5;
						r3 = p3/5;
						c3 = p3%5;
						if(standBoard[r3][c3] == 0x00 || standBoard[r3][c3]==0x14 ||standBoard[r3][c3]==0x13)continue;
						break;
					}
					swapChess(standBoard,5,i,r3,c3);
				}
			}
			return standBoard;
		}
		
		private function swapChess(chessBoard:Array,r1:int,c1:int,r2:int,c2:int):void
		{
			var temp:int = chessBoard[r1][c1];
			chessBoard[r1][c1]= chessBoard[r2][c2];
			chessBoard[r2][c2] = temp;
		}
		
		public function printBoardArea()
		{
			for(var i=0;i<12;i++){
				trace(boardArea[i][0]+","+boardArea[i][1]+","+boardArea[i][2]+","+boardArea[i][3]+","+boardArea[i][4]);
			}
		}
		/**
	 		* Initiate the board
	 	*/
		public function initBoard():void {
			initDefaultBoard();
			if(boardArea.length <=0) {
				for (var i:int = 0; i < Board.BOARD_HEIGHT; i++) {
					boardArea.push(new Array());
					stations.push(new Array());
				}
			}
			for (var y:int = 0; y < Board.BOARD_HEIGHT; y++) {
				for (var x:int = 0; x < Board.BOARD_WIDTH; x++) {
					if(defaultBoard[y][x] != Board.INVALID_BOARD_TAG) {
						robot.AddPiece(y,x,defaultBoard[y][x]);
					}
					else {
						boardArea[y][x] = defaultBoard[y][x];
					}
					// stations
					if ((y == 0 || y == 11) && (x == 1 || x == 3)) {
						stations[y][x] = Board.HEADQUARTER;
					} else if ((y == 2 || y == 4 || y == 7 || y == 9)
						&& (x == 1 || x == 3) || (y == 3 || y == 8) && x == 2) {
						stations[y][x] = Board.CAMP;
					} else if (y == 1 || y == 5 || y == 6 || y == 10 || x == 0
						&& y != 0 && y != 11 || x == 4 && y != 0 && y != 11) {
						stations[y][x] = Board.STATION_RAILWAY;
					} else {
						stations[y][x] = Board.STATION_ROAD;
					}
			
				}
			}
		
			mPath = null;
			from = to = from0 = to0 = null;
			curStep = 0;
			mSourcePiece = Board.INVALID_BOARD_TAG;
			moveAndAttackResult = Board.INVALID_MOTION;
		}
		
		//加载标准棋子
		public function loadAllChess()
		{
			this.GameState = Board.GS_PLAYING;
			if(allChess == null) {
				allChess = new Dictionary();
			}
			else {
				for (var id:* in allChess)
				{  
					var chess:Chess = allChess[id];
					if(chess == null) continue;
					removeChild(chess);
					allChess[id] = null;
				}
			}
			this.initBoard();
			for (var y:int = 0; y < Board.BOARD_HEIGHT; y++) {
				for (var x:int = 0; x < Board.BOARD_WIDTH; x++) {
					if(boardArea[y][x] != Board.INVALID_BOARD_TAG) {
						var chessValue = boardArea[y][x];
						var side = Pieces.getLocated(chessValue);
						var pureType = Pieces.getPureType(chessValue);
						chess = new Chess(side);
						var p:Point = Main.instance.rowcolToPostion(y,x);
						chess.x = p.x;
						chess.y = p.y;
						chess.setTitle(Pieces.pieceTitle(pureType));
						addChild(chess);
						var key = y+"_"+x;
						
						chess.backVisible = true;
						allChess[key] = chess;
					}
				}
			}
			robot.resetAI();
			steps = 0;
			if(flipTimer == null) {
				flipTimer = new Timer(1000,1);
				flipTimer.addEventListener(TimerEvent.TIMER_COMPLETE,showAllChess);
			}
			flipTimer.start();
			showPath(0,0,null);
		}
		
		private function showAllChess(e:TimerEvent):void 
		{
			for (var id:* in allChess)
				{  
					var chess:Chess = allChess[id];
					if(chess == null) continue;
					chess.backVisible = false;
				}
		}
		
		private function getChessAt(row:int,col:int):Chess
		{
			var key = row+"_"+col;
			return allChess[key];
		}
		
		public function validXY (chessX:int,chessY:int):Boolean {
			return chessX >=0 && chessX < Board.BOARD_WIDTH && chessY >=0 && chessY < Board.BOARD_HEIGHT;
		}
	
		public function validYX ( chessY:int, chessX:int):Boolean {
			return validXY(chessX, chessY);
		}
	
		public function getStations():Array {
			return stations;
		}

		public function get ba():Array {
			return boardArea;
		}

		public function setBoardArea(boardArea:Array):void {
			this.boardArea = boardArea;
		}

		public function clearFromTo():void{
			from = null;
			to = null;
		}
		
		public function setFromTo(whosTurn:int,c:Coordinate):Boolean {
			if (from == null && whosTurn == Pieces.getLocated(boardArea[c.y][c.x])){
				from = c;
				to = null;
				return true;
			} else if (from == null && whosTurn != Pieces.getLocated(boardArea[c.y][c.x])){
				to = null;
				return false;
			} else if (to == null) {
				 var x:int = from.x;
				 var y:int = from.y;
				 var x0:int = c.x;
				 var y0:int = c.y;
				// Check if user changes the "from" selection
				if (Pieces.sameLocation( boardArea[y0][x0], boardArea[y][x])){
					from = c;
				} 
				else {
					to = c;
				}
				return true;
			} else { 
				// both are not null. It's not allowed to come here
				//Log.e(this.getClass().getName(), "// both are not null. It's not allowed to come here!");
				return false;
			}
		}
		
		public function tryToMove():void {
			if (from == null || to == null) {
				return;
			}
			// path finding
			mPath = pathFinding(from.x, from.y, to.x, to.y);
			if (mPath == null || mPath.length<1) {
				from0 = from ;
				to0 = to;
				from = null;
				to = null;
				mPath = null;
				curStep = 0;
				return; 
			}

			moveAndAttackResult = moveAndAttack(from.x, from.y, to.x, to.y);
		}
		
		 private function moveAndAttack (x0:int,y0:int,x:int,y:int):int {
			// Validation
			if (stations[y0][x0] == Board.INVALID_BOARD_TAG || stations[y][x] == Board.INVALID_BOARD_TAG
				|| boardArea[y0][x0] == Board.INVALID_BOARD_TAG || boardArea[y][x] != Board.INVALID_BOARD_TAG
				&& Pieces.sameLocation(boardArea[y0][x0], boardArea[y][x])) {
				return Board.INVALID_MOTION;
			}
			// Move only
			if (boardArea[y][x] == INVALID_BOARD_TAG) {
				return Board.MOVE;
			}
			// Attack
			if (Pieces.getPureType(boardArea[y][x]) == Pieces.FLAG_S) {
				var locatedLost:int = Pieces.getLocated(boardArea[y][x]);
				// One lost
				return locatedLost > 0 ? AI_LOST:MAN_LOST; 
			} else if (Pieces.getPureType(boardArea[y0][x0]) == Pieces.BOMB_S
				|| Pieces.getPureType(boardArea[y][x]) == Pieces.BOMB_S) {
				// Bomb
				return Board.EQUAL;
			} else if (Pieces.getPureType(boardArea[y][x]) == Pieces.MINE_S) {
				if (Pieces.getPureType(boardArea[y0][x0]) == Pieces.GONGBING_S) {
					// Mine
					return Board.KILL;
				} else {
					return Board.EQUAL;
				}
			} else {
				// Soldiers
				var soldier0:int = Pieces.getPureType(boardArea[y0][x0]);
				var soldier1:int = Pieces.getPureType(boardArea[y][x]);
				if (soldier0 < soldier1) {
					return Board.KILL;
				} else if (soldier0 == soldier1) {
					return Board.EQUAL;
				} else {
					return Board.KILLED;
				}
			}
		}
		
		//used by ABSearch
		public function makeaMove (move:Movement):void {
			if (move == null){
				return ;
			}
			var from:Coordinate = move.getStart();
			var to:Coordinate = move.getEnd();
		
			var result:int = moveAndAttack(from.x, from.y, to.x, to.y);
			var srcChess:int =  boardArea[from.y][from.x];
			var dstChess:int = boardArea[to.y][to.x];
			switch (result) {
				case MOVE:
				case KILL:
				case AI_LOST:
				case MAN_LOST:
					robot.DelPiece(from.y,from.x);
					robot.DelPiece(to.y,to.x);
					robot.AddPiece(to.y,to.x,srcChess);
					
					break;
				case EQUAL:
					robot.DelPiece(from.y,from.x);
					robot.DelPiece(to.y,to.x);
					break;
				case KILLED:
					robot.DelPiece(from.y,from.x);
				break;
			}
		
		
		}
		
		private function addToStage(e:Event)
		{
			mcSelected = new SelBox();
			addChild(mcSelected);
			mcSelected.visible = false;
			
		}
		
		

		/**
		 * Path finding
	 	* @param x0
	 	* @param y0
	 	* @param x
	 	* @param y
	 	* @return Vector<Coordiante>  doesn't include the source
	 	*/
		public function pathFinding(x0:int,y0:int,x:int,y:int):Array  {
			// No piece in x0,y0 or The pieces in HEADQUARTER and the mines can NOT move
			if (boardArea[y0][x0]== INVALID_BOARD_TAG || stations[y0][x0] == Board.HEADQUARTER
				|| Pieces.getPureType(boardArea[y0][x0]) == Pieces.MINE_S) {
				return null;
			}
			// Can not move to a camp which is occupied
			if (stations[y][x] == Board.CAMP && boardArea[y][x] != Board.INVALID_BOARD_TAG) {
				return null;
			}
			// Piece -> Piece which are belong to the same player
			if (Pieces.sameLocation(boardArea[y0][x0], boardArea[y][x])) {
				return null;
			}

			var beginning:Coordinate  = new Coordinate(x0+y0*100);
			var end:Coordinate  = new Coordinate(x+100*y);
			var path:Array = new Array();
		
			// Road station or Camp ( | - ) , move only 1 step
			if (stations[y0][x0] == STATION_ROAD || stations[y][x] == STATION_ROAD
				|| stations[y0][x0] == CAMP || stations[y][x] == CAMP
				|| stations[y][x] == HEADQUARTER) {
				if (roadAdjacent(x0, y0, x, y)) {
					path.push(new Coordinate(x+100*y));
					return path;
				}
			}
		
			// Camp, move only 1 step (/ \)
			if (stations[y0][x0] == CAMP || stations[y][x] == CAMP) {
				if (campAdjacent(x0, y0, x, y)) {
					path.push(new Coordinate(x+100*y));
					return path;
				}
			}
		
			// on Railway, A* path finding
			openList = new Array();
			closedList = new Array();
			
			if (stations[y0][x0] == STATION_RAILWAY	&& stations[y][x] == STATION_RAILWAY &&
				(validRailwayRoad(x0, y0, x, y) || Pieces.getPureType(boardArea[y0][x0]) == Pieces.GONGBING_S)) 
			{
				var adjacent:Array = new Array();
				var engineer:Boolean = Pieces.getPureType(boardArea[y0][x0]) == Pieces.GONGBING_S;
				var current:Coordinate = null;
				openList.push(beginning);
			
				do {
					// Find the minimum F value Coordinate from the openList
					current = lookForMinF(end);
					//yfxu modiy
					var index = openList.indexOf(current);
					openList.splice(index,1);
					closedList.push(current);
					// Get all adjacent XYs of current
					adjacent = allAdjacents(beginning, current, end, engineer);
				

					for each(var adj:Coordinate in adjacent) { // Traverse all adjacent of
						// current Coordinate
						if (!closedListContains(adj)
							&& (boardArea[adj.y][adj.x] == Pieces.INVALID || adj.equals(end))) {
							if (!openListContains(adj)) {
								adj.parent = current;
								openList.push(adj);
							} else {
								if (getCostG(current.parent, current)
										+ getCostG(current, adj) < getCostG(
									current.parent, adj)) {
									adj.parent = current;
								}
							}
						}
					}
				} while (!openListContains(end) && openList.length > 0);
				end.parent = current;

				if (openListContains(end)) { // Find the path
					var t:Coordinate = end;
					while (t != beginning) {
						path.push(t);
						t = t.parent;
					}
				}
			}
		
			for (var i:int = path.length - 1; i > (path.length - 1) / 2; i--) {
				var tmp:Coordinate = path[i];
				path[i] = path[path.length - 1 - i];
				path[path.length - 1 - i] =  tmp;
			}	
			return path;
		}
	
		/**
	 	* Get the adjacent points of current
	 	*/
		private function allAdjacents(beginning:Coordinate,
			 current:Coordinate, end:Coordinate,engineer:Boolean):Array  {
			var adjacent:Array  = new Array();

			if (engineer) {
				for (var i:int = -1; i <= 1; i += 2) {
					if (validYX(current.y + i, current.x) && 
						stations[current.y + i][current.x] == STATION_RAILWAY) 
					{
						if(!((current.y ==5) && (current.x == 1)
							   ||(current.y ==5) && (current.x == 3)
							   ||(current.y ==6) && (current.x == 1)
							   ||(current.y ==6) && (current.x == 3))
							)
						{
							adjacent.push(new Coordinate(current.x+ 100*(current.y + i)));
						}
					}
					if (validYX(current.y , current.x+i) &&
						stations[current.y][current.x + i] == STATION_RAILWAY) {
						adjacent.push(new Coordinate(current.x + i+100*current.y));
					}
				}
			} else { // Not the engineer
				for (i = -1; i <= 1; i += 2) { // The beginning and end are on
					// the same row/column
					if (current.x == end.x
						&& validYX(current.y + i, current.x) 
						&& stations[current.y + i][current.x] == STATION_RAILWAY) 
					{
						if(!((current.y ==5) && (current.x == 1)
							   ||(current.y ==5) && (current.x == 3)
							   ||(current.y ==6) && (current.x == 1)
							   ||(current.y ==6) && (current.x == 3))
							)
						{
							adjacent.push(new Coordinate(current.x + 100*(current.y + i)));
						}
					}
					if (current.y == end.y
						&& validYX(current.y , current.x+i)
						&& stations[current.y][current.x + i] == STATION_RAILWAY) {
						adjacent.push(new Coordinate(current.x + i+100*current.y));
					}  
				}
			}
			return adjacent;
		}
		
		/**
		 * True if openList contains the target
		 */
		private function openListContains(target:Coordinate):Boolean {
			for each(var c:Coordinate  in openList) {
				if (c.equals(target))
				return true;
			}
			return false;
		}

		/**
	 	* True if closedList contains the target
	 	*/
		private function closedListContains(target:Coordinate):Boolean {
			for each(var c:Coordinate in closedList) {
				if (c.equals(target))
					return true;
			}
			return false;
		} 
		
		/**
	 	* Look for the Coordinate that has the minimum F value from openList list
	 	*/
		private function lookForMinF(target:Coordinate):Coordinate {
			var c:Coordinate = openList[0];
			for (var i:int = 1; i < openList.length; i++) {
				var tmp:Coordinate = openList[i] as Coordinate;
				if ( (getCostG(tmp.parent, tmp) + getDistanceH2(tmp, target)) 
					< 
					(getCostG(c.parent, c) + getDistanceH2(c, target)) ) {
					c = tmp;
				}
			}
			return c;
		}
		
		/**
			 * The G function - cost from c0 to c1
	 	*/
		private function getCostG(c0:Coordinate,c1:Coordinate):int {
			// c.parent compare to c, if c is the beginning, then c.parent is NULL
			if (c0 == null || c1 == null) {
				return 0;
			}

			// Validation
			if (stations[c0.y][c0.x] == Pieces.INVALID
				|| stations[c1.y][c1.x] == Pieces.INVALID) {
				return int.MAX_VALUE
			}

			if (c0.x == c1.x || c0.y == c1.y) {
				return Math.abs(c0.x - c1.x) * 10 + Math.abs(c0.y - c1.y) * 10;
			} else if (Math.abs(c0.x - c1.x) == 1 && Math.abs(c0.y - c1.y) == 1) {
				return 14;
			} else {
				return int.MAX_VALUE;
			}
		}
		
		/**
	 		* The H function - Manhattan distance from x0,y0 to x,y
		 */
		private function getDistanceH(x0:int,y0:int,x:int,y:int):int {
			return (Math.abs(x0 - x) + Math.abs(y0 - y)) * 10;
		}
		/**
		 * The H function - Manhattan distance from c0 to c1
		 */
		private function getDistanceH2(c0:Coordinate,c1:Coordinate):int {
			return getDistanceH(c0.x, c0.y, c1.x, c1.y);
		}
	
		
		
		/**
		 * Road adjacent
		 */
		private function roadAdjacent(x0:int,y0:int,x:int,y:int):Boolean {
			return x0 == x && Math.abs(y0 - y) == 1 || y0 == y && Math.abs(x0 - x) == 1;
		}
		/**
	 	* Camp adjacent
	 	*/
		private function campAdjacent(x0:int,y0:int,x:int,y:int):Boolean {
			return Math.abs(x0 - x) == 1 && Math.abs(y0 - y) == 1;
		}
		
		/**
	 	* Valid railway road
	 	*/
		private function validRailwayRoad(x0:int,y0:int,x:int,y:int):Boolean {
			return x0 == x 	|| y0 == y;
			/*
		 	return  x0 == x && ( x == 0 || x == 4 || x == 2 && y >= 5 && y <=6) 
				||  y0 == y && (y == 1 || y == 5 || y == 6 || y == 10);	
			*/ 
		}
		
		public function getFrom():Coordinate {
			return from;
		}

		public function setFrom(from:Coordinate):void {
			this.from = from;
		}

		public function getTo():Coordinate {
			return to;
		}

		public function setTo(to:Coordinate):void {
			this.to = to;
		}

		public function getFrom0():Coordinate {
			return from0;
		}

		public function setFrom0(from0:Coordinate):void {
			this.from0 = from0;
		}

		public function getTo0():Coordinate {
			return to0;
		}

		public function setTo0(to0:Coordinate):void {
			this.to0 = to0;
		}

		public function getMoveAndAttackResult():int {
			return moveAndAttackResult;
		}

		public function setMoveAndAttackResult(moveAndAttackResult:int ):void {
			this.moveAndAttackResult = moveAndAttackResult;
		}
		
		public function onTimer(e:TimerEvent)
		{
			robot.aiMove();
		}
		
		public function robotMove(oRow:int,oCol:int,row:int,col:int):void
		{
			if(this.GameState == GS_PLAYING)
			{
				mPath = pathFinding(oCol,oRow , col,row);
				if (mPath == null || mPath.length<1) {
					return;
				}
				this.mcSelected.visible = false;
				imgThink.visible = false;
				showPath(oRow,oCol,mPath);
				moveAndAttackResult = moveAndAttack(oCol,oRow , col,row);
				var chess:Chess = this.getChessAt(oRow,oCol);
				var targetChess:Chess = this.getChessAt(row,col);
				lastSelected = -1;
				var msg:String = "";
				var srcChess:int =  boardArea[oRow][oCol];
				var dstChess:int = boardArea[row][col];
				robot.MakeMoveRC(oRow,oCol,row,col);
				switch (moveAndAttackResult) {
					case MOVE:
					case KILL:
					case AI_LOST:
					case MAN_LOST:

						robot.DelPiece(oRow,oCol);
						robot.DelPiece(row,col);
						robot.AddPiece(row,col,srcChess);
						var p2:Point = Main.instance.rowcolToPostion(row,col);
						chess.x = p2.x;
						chess.y = p2.y;						
						if(targetChess != null) {
							this.removeChild(targetChess);
							msg = msg+"敌人的"+chess.title+"消灭了你的"+targetChess.title+".";

						}
						setChess(row,col,chess);
						setChess(oRow,oCol,null);
						
					break;
					case EQUAL:
						msg = msg+"敌人的"+chess.title+"和你的"+targetChess.title+"同归于尽了.";

						robot.DelPiece(oRow,oCol);
						robot.DelPiece(row,col);
						this.removeChild(targetChess);
						this.removeChild(chess);
						setChess(row,col,null);
						setChess(oRow,oCol,null);
					break;
					case KILLED:
						msg = msg+"敌人的"+chess.title+"被你的"+targetChess.title+"干掉了.";

						robot.DelPiece(oRow,oCol);
						this.removeChild(chess);
						setChess(oRow,oCol,null);
					break;
				}
				(new sndMove).play();
				Main.instance.showMessage(msg);
				steps++;
				this.checkGame();
				robot.printZobr();
			}
			
		}
		
		function showPath(oRow:int,oCol:int,path:Array) {
		//show path
				var lastArrow:MovieClip = null;
				mcSelected.visible = false;
				for each(var ppTemp:MovieClip in allPathPoint) {
					removeChild(ppTemp);
				}
				allPathPoint.length = 0;
				if(path == null) return;
				
				allPathPoint.length = 0;
				var pp:MovieClip = new PathPoint();
				var p:Point = Main.instance.rowcolToPostion(oRow,oCol);
				pp.x = p.x+30;
				pp.y = p.y+15;
				pp.width = 20;
				pp.height = 20;
				
				addChild(pp);
				allPathPoint.push(pp);
				var prevR = oRow;
				var prevC = oCol;
				lastArrow = pp;
				var tp:Coordinate = null;
				for(var i=0;i<mPath.length;i++) {
					tp = mPath[i];
					var curR = tp.y;
					var curC = tp.x;
					if(lastArrow != null) {
						var ofr = curR - prevR;
						var ofc = curC - prevC;
						trace(ofr + "  "+ ofc);
						
						if(ofr== 0 && ofc == 1) lastArrow.rotation = 0;//donothin
						if(ofr == 0 && ofc == -1) lastArrow.rotation = 180;
						if(ofr == 1 && ofc == 0) lastArrow.rotation = 90;
						if(ofr == -1 && ofc == 0) lastArrow.rotation = -90;
						
						if(ofr == -1 && ofc == 1) lastArrow.rotation = -35;
						if(ofr == -1 && ofc == -1) lastArrow.rotation = -145;
						if(ofr == 1 && ofc == 1) lastArrow.rotation = 35;
						if(ofr == 1 && ofc == -1) lastArrow.rotation = 145;
						
						
					}
					if(i < (mPath.length-1)) {
						pp = new PathPoint();
						p = Main.instance.rowcolToPostion(tp.y,tp.x);
						pp.x = p.x;
						pp.y = p.y;
						pp.x = p.x+30;
						pp.y = p.y+15;
						pp.width = 20;
						pp.height = 20;
						addChild(pp);
						allPathPoint.push(pp);
						lastArrow = pp;
						prevR = curR;
						prevC = curC;
					}else {
						lastArrow = null;
					}

				}
				p = Main.instance.rowcolToPostion(tp.y,tp.x);
				var endBox = new SelBox();
				endBox.x = p.x;
				endBox.y = p.y;
				addChild(endBox);
				allPathPoint.push(endBox);
		}
		
		private function checkGame()
		{
			var gr:int = -100;
			var northChess:int = 0;
			var southChess:int = 0;
			if(steps > Board.MAX_STEP) {
				gr = 0;
				(new sndWin).play();
				Main.instance.showMessage("规定的步数内未分胜负。");
			}
			else if(boardArea[0][1] != 0x12 && boardArea[0][3]!=0x12){
				gr = 1;
				(new sndWin).play();
			}
			else if(boardArea[11][1] != 0x02 && boardArea[11][3]!=0x02){
				gr = -1;
				(new sndLose).play();
			}
			
			
			for(var r:int =0;r<12;r++) {
				for(var c:int =0;c<5;c++) {
					var chess = boardArea[r][c];
					if(chess == Pieces.INVALID) continue;
					if(r == 0 && (c == 1||c ==3 )) continue;
					if(r == 11 && (c == 1||c == 3)) continue;
					if(chess>=Pieces.BOMB_S && chess<=Pieces.GONGBING_S) {
						southChess++;
					}
					if(chess>=Pieces.BOMB_N && chess<=Pieces.GONGBING_N) {
						northChess++;
					}
				}
			}
			if(gr == -100) {
				if(southChess == 0 && northChess == 0) {
					gr = 0;
					(new sndWin).play();
					Main.instance.showMessage("都没棋可走了。");
				}
				else if(southChess == 0 && northChess>0) {
					gr = -1;
					(new sndLose).play();
					Main.instance.showMessage("你没棋子可以走了。");
				}
				else if(southChess >0 && northChess==0) {
					gr = 1;
					(new sndWin).play();
					Main.instance.showMessage("电脑被你打败了。");
				}
			}
			
			imgThink.visible = false;
			if(gr != -100) {
				Main.instance.showGameResult(gr);
				this.GameState = Board.GS_OVER;
			}
		}
		//
		
		
	}//end of class
	
}//end of package
